package com.authority.framework.config.shiro;

import com.authority.framework.log.manager.AsyncManager;
import com.authority.framework.log.manager.factory.AsyncFactory;
import com.authority.framework.web.domain.*;
import com.authority.framework.web.service.*;
import com.authority.framework.base.util.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.*;

import static com.authority.framework.base.util.EncryptPassword.encryptPassword;

/**
 * @author SPPan
 */
@Component
/*@Import(ShiroManager.class)*/
public class MyRealm extends AuthorizingRealm {

	// 密码加密方式
	@Value("${shiro.user.hashAlgorithmName}")
	private String hashAlgorithmName;

	// 密码加密次数
	@Value("${shiro.user.hashIterations}")
	private Integer hashIterations;


	public MyRealm() {
		super(new AllowAllCredentialsMatcher());
		setAuthenticationTokenClass(UsernamePasswordToken.class);

		//FIXME: 暂时禁用Cache
		setCachingEnabled(false);
	}

	@Autowired
	private PrivLoginService privLoginService;

	@Autowired
	private SysRoleService sysRoleService;

	@Autowired
	private SysMenuService sysMenuService;

	@Autowired
	private SysDeptService sysDeptService;

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		SysUserEntity user = (SysUserEntity) principals.getPrimaryPrincipal();
		// 角色列表
		Set<String> roles = new HashSet<String>();
		// 功能列表
		Set<String> menus = new HashSet<String>();
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		// 管理员拥有所有权限
		if (user.isAdmin()) {
			info.addRole("admin");
			info.addStringPermission("*:*:*");
		} else {
			//  用户角色
			List<SysRoleEntity> entityPerms = sysRoleService.findListByUserId(user.getUserId().intValue());
			if (StringUtils.isNotNull(entityPerms)) {
				for (SysRoleEntity perm : entityPerms) {
					if (StringUtils.isNotNull(perm)) {
						roles.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
					}
				}
			}
			Map<String,Object> paramMap = new HashMap<>();
			paramMap.put("userId",user.getUserId().toString());
			//  用户菜单
			List<SysMenuEntity> menuPerms = sysMenuService.findListByUserId(paramMap);
			if (StringUtils.isNotNull(menuPerms)) {
				for (SysMenuEntity perm : menuPerms) {
					if (StringUtils.isNotNull(perm) && StringUtils.isNotEmpty(perm.getPerms())) {
						menus.addAll(Arrays.asList(perm.getPerms().trim().split(",")));
					}
				}
			}
			// 角色加入AuthorizationInfo认证对象
			info.setRoles(roles);
			// 权限加入AuthorizationInfo认证对象
			info.setStringPermissions(menus);
		}
		return info;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		String username = upToken.getUsername();
		String password = "";

		if (upToken.getPassword() != null) {
			password = encryptPassword(hashAlgorithmName, new String(upToken.getPassword()), null, hashIterations);
		}
		SysUserEntity user = null;
		try {
			user = privLoginService.login(username, password);
		}
		catch (Exception e) {
			AsyncManager.me().execute(AsyncFactory.recordLogininfor(username,"1","账号或密码不正确"));
			throw new UnknownAccountException("账号或密码不正确");
		}
		// 账号不存在
		if (user == null) {
			AsyncManager.me().execute(AsyncFactory.recordLogininfor(username,"1","账号或密码不正确"));
			throw new UnknownAccountException("账号或密码不正确");
		} else {
			AsyncManager.me().execute(AsyncFactory.recordLogininfor(username,"0","登录成功"));
			//  用户角色
			List<SysRoleEntity> entityPerms = sysRoleService.findListByUserId(user.getUserId().intValue());
			if (StringUtils.isNotNull(entityPerms)) {
				user.setRoles(entityPerms);
				Long [] roles = new Long[entityPerms.size()];
				for (int i = 0 ; i <entityPerms.size();i++){
					roles[i] = entityPerms.get(i).getRoleId();
				}
				user.setRoleIds(roles);
			}
			//  用户部门
			SysDeptEntity Dept = sysDeptService.findByPrimaryKey(SysDeptEntity.class, user.getDeptId().intValue());
			if (StringUtils.isNotNull(Dept)) {
				user.setDept(Dept);
			}
		}

		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());

		return info;
	}

}
